home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1993 July / Internet Tools.iso / RockRidge / mail / pine / pine3.07 / c-client / mtest.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-05-06  |  13.6 KB  |  566 lines

  1. /*
  2.  * Program:    Mail library test program
  3.  *
  4.  * Author:    Mark Crispin
  5.  *        Networks and Distributed Computing
  6.  *        Computing & Communications
  7.  *        University of Washington
  8.  *        Administration Building, AG-44
  9.  *        Seattle, WA  98195
  10.  *        Internet: MRC@CAC.Washington.EDU
  11.  *
  12.  * Date:    8 July 1988
  13.  * Last Edited:    6 May 1992
  14.  *
  15.  * Sponsorship:    The original version of this work was developed in the
  16.  *        Symbolic Systems Resources Group of the Knowledge Systems
  17.  *        Laboratory at Stanford University in 1987-88, and was funded
  18.  *        by the Biomedical Research Technology Program of the National
  19.  *        Institutes of Health under grant number RR-00785.
  20.  *
  21.  * Original version Copyright 1988 by The Leland Stanford Junior University.
  22.  * Copyright 1992 by the University of Washington.
  23.  *
  24.  *  Permission to use, copy, modify, and distribute this software and its
  25.  * documentation for any purpose and without fee is hereby granted, provided
  26.  * that the above copyright notices appear in all copies and that both the
  27.  * above copyright notices and this permission notice appear in supporting
  28.  * documentation, and that the name of the University of Washington or The
  29.  * Leland Stanford Junior University not be used in advertising or publicity
  30.  * pertaining to distribution of the software without specific, written prior
  31.  * permission.  This software is made available "as is", and
  32.  * THE UNIVERSITY OF WASHINGTON AND THE LELAND STANFORD JUNIOR UNIVERSITY
  33.  * DISCLAIM ALL WARRANTIES, EXPRESS OR IMPLIED, WITH REGARD TO THIS SOFTWARE,
  34.  * INCLUDING WITHOUT LIMITATION ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
  35.  * FITNESS FOR A PARTICULAR PURPOSE, AND IN NO EVENT SHALL THE UNIVERSITY OF
  36.  * WASHINGTON OR THE LELAND STANFORD JUNIOR UNIVERSITY BE LIABLE FOR ANY
  37.  * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
  38.  * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
  39.  * CONTRACT, TORT (INCLUDING NEGLIGENCE) OR STRICT LIABILITY, ARISING OUT OF
  40.  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  41.  *
  42.  */
  43.  
  44. #include <stdio.h>
  45. #include <ctype.h>
  46. #include <signal.h>
  47. #if unix
  48. #include <sys/types.h>
  49. #include <pwd.h>
  50. #include <netdb.h>
  51. #endif
  52. #include "osdep.h"
  53. #ifdef noErr
  54. #include <MacTCPCommonTypes.h>
  55. #include <AddressXlation.h>
  56. #endif
  57. #include "mail.h"
  58. #include "rfc822.h"
  59. #include "smtp.h"
  60. #include "nntp.h"
  61. #include "misc.h"
  62.  
  63.  
  64. char *curhst = NIL;        /* currently connected host */
  65. char *curusr = NIL;        /* current login user */
  66. char personalname[256];        /* user's personal name */
  67. extern DRIVER imapdriver,bezerkdriver,tenexdriver,mboxdriver,mhdriver,
  68.  newsdriver,dummydriver;
  69.  
  70. static char *hostlist[] = {    /* SMTP server host list */
  71.   "mailhost",
  72.   "localhost",
  73.   NIL
  74. };
  75.  
  76. static char *newslist[] = {    /* Netnews server host list */
  77.   "news",
  78.   NIL
  79. };
  80.  
  81. void main  ();
  82. void mm  ();
  83. void header  ();
  84. void status  ();
  85. void prompt  ();
  86. void smtptest  ();
  87.  
  88. /* Main program - initialization */
  89.  
  90. void main ()
  91. {
  92.   MAILSTREAM *stream = NIL;
  93.   char tmp[MAILTMPLEN];
  94.   long debug;
  95. #ifdef noErr
  96.   size_t *base = (size_t *) 0x000908;
  97.                 /* increase stack size on a Mac */
  98.   SetApplLimit ((Ptr) (*base - (size_t) 65535L));
  99. #endif
  100. #if unix
  101.   char *name;
  102.   char *suffix;
  103.   struct passwd *pwd;
  104.   struct hostent *host_name;
  105.   gethostname (tmp,MAILTMPLEN);    /* get local name */
  106.                 /* get it in full form */
  107.   curhst = (host_name = gethostbyname (tmp)) ?
  108.     cpystr (host_name->h_name) : cpystr (tmp);
  109.                 /* get user name and passwd entry */
  110.   if (name = (char *) getlogin ()) pwd = getpwnam (name);
  111.   else {
  112.     pwd = getpwuid (getuid ());    /* get it this way if detached, etc */
  113.     name = pwd->pw_name;
  114.   }
  115.   curusr = cpystr (name);    /* current user is this name */
  116.   strcpy (tmp,pwd->pw_gecos);    /* probably not necessay but be safe */
  117.                 /* dyke out the office and phone poop */
  118.   if (suffix = strchr (tmp,',')) suffix[0] = '\0';
  119.   strcpy (personalname,tmp);    /* make a permanent copy of it */
  120. #else
  121.   prompt ("Personal name: ",personalname);
  122. #endif
  123.   puts ("MTest -- C client test program");
  124.   mail_link (&imapdriver);    /* link in IMAP driver */
  125. #if unix
  126.   mail_link (&tenexdriver);    /* link in Tenex mail driver */
  127.   mail_link (&mhdriver);    /* link in mh mail driver */
  128.   mail_link (&mboxdriver);    /* link in mbox mail driver */
  129.   mail_link (&bezerkdriver);    /* link in Berkeley mail driver */
  130.   mail_link (&newsdriver);    /* link in netnews mail driver */
  131.   mail_link (&dummydriver);    /* finally dummy driver at the end */
  132. #endif
  133.                 /* user wants protocol telemetry? */
  134.   prompt ("Debug protocol (y/n)?",tmp);
  135.   ucase (tmp);
  136.   debug = (tmp[0] == 'Y') ? T : NIL;
  137.   do {
  138.     prompt ("Mailbox ('?' for help): ",tmp);
  139.     if (!strcmp (tmp,"?")) {
  140. #if unix
  141.       puts ("Enter INBOX, a mailbox name, or an IMAP mailbox as {host}mailbox");
  142.       puts ("Known local mailboxes:");
  143.       mail_find (NIL,"*");
  144. #else
  145.       puts ("Enter an IMAP mailbox as {host}mailbox");
  146. #endif
  147.       puts ("or just hit return to quit");
  148.     }
  149.     else if (tmp[0]) stream = mail_open (stream,tmp,debug);
  150.   } while (!stream && tmp[0]);
  151.   mm (stream,debug);        /* run user interface if opened */
  152. #ifdef __MSDOS__
  153.   netshut ();            /* clean up */
  154. #endif
  155. #ifdef noErr
  156.                 /* clean up resolver */
  157.   if (resolveropen) CloseResolver ();
  158. #endif
  159. }
  160.  
  161. /* MM command loop
  162.  * Accepts: MAIL stream
  163.  */
  164.  
  165. void mm (stream,debug)
  166.     MAILSTREAM *stream;
  167.     long debug;
  168. {
  169.   char cmd[256];
  170.   char *arg;
  171.   long i;
  172.   long last = 0;
  173.   status (stream);        /* first report message status */
  174.   while (stream) {
  175.     prompt ("MTest>",cmd);    /* prompt user, get command */
  176.                 /* get argument */
  177.     if (arg = strchr (cmd,' ')) *arg++ = '\0';
  178.     switch (*ucase (cmd)) {    /* dispatch based on command */
  179.       case 'C':            /* Check command */
  180.     mail_check (stream);
  181.     status (stream);
  182.     break;
  183.       case 'D':            /* Delete command */
  184.     if (arg) last = atoi (arg);
  185.     else {
  186.       if (last == 0) {
  187.         puts ("?Missing message number");
  188.         break;
  189.       }
  190.       arg = cmd;
  191.       sprintf (arg,"%ld",last);
  192.     }
  193.     if (last > 0 && last <= stream->nmsgs)
  194.       mail_setflag (stream,arg,"\\DELETED");
  195.     else puts ("?Bad message number");
  196.     break;
  197.       case 'E':            /* Expunge command */
  198.     mail_expunge (stream);
  199.     last = 0;
  200.     break;
  201.       case 'F':            /* Find command */
  202.     puts ("Known mailboxes:");
  203.     mail_find (stream,"*");
  204.     puts ("Known bboards:");
  205.     mail_find_bboards (stream,"*");
  206.     break;
  207.       case 'G':
  208.     mail_gc (stream,GC_ENV|GC_TEXTS|GC_ELT);
  209.     break;
  210.       case 'H':            /* Headers command */
  211.     if (arg) {
  212.       if (!(last = atoi (arg))) {
  213.         mail_search (stream,arg);
  214.         for (i = 1; i <= stream->nmsgs; ++i)
  215.           if (mail_elt (stream,i)->searched) header (stream,i);
  216.         break;
  217.       }
  218.     }
  219.     else if (last == 0) {
  220.       puts ("?Missing message number");
  221.       break;
  222.     }
  223.     if (last > 0 && last <= stream->nmsgs) header (stream,last);
  224.     else puts ("?Bad message number");
  225.     break;
  226.       case 'N':            /* New mailbox command */
  227.     if (!arg) {
  228.       puts ("?Missing mailbox");
  229.       break;
  230.     }
  231.                 /* get the new mailbox */
  232.     while (!(stream = mail_open (stream,arg,debug)))
  233.       prompt ("Mailbox: ",arg);
  234.     last = 0;
  235.     status (stream);
  236.     break;
  237.       case 'Q':            /* Quit command */
  238.     mail_close (stream);
  239.     stream = NIL;
  240.     break;
  241.       case 'S':            /* Send command */
  242.     smtptest (debug);
  243.     break;
  244.       case 'T':            /* Type command */
  245.     if (arg) last = atoi (arg);
  246.     else if (last == 0 ) {
  247.       puts ("?Missing message number");
  248.       break;
  249.     }
  250.     if (last > 0 && last <= stream->nmsgs) {
  251.       printf ("%s",mail_fetchheader (stream,last));
  252.       puts (mail_fetchtext (stream,last));
  253.     }
  254.     else puts ("?Bad message number");
  255.     break;
  256.       case 'U':            /* Undelete command */
  257.     if (arg) last = atoi (arg);
  258.     else {
  259.       if (last == 0 ) {
  260.         puts ("?Missing message number");
  261.         break;
  262.       }
  263.       arg = cmd;
  264.       sprintf (arg,"%ld",last);
  265.     }
  266.     if (last > 0 && last <= stream->nmsgs)
  267.       mail_clearflag (stream,arg,"\\DELETED");
  268.     else puts ("?Bad message number");
  269.     break;
  270.       case 'X':            /* Xit command */
  271.     mail_expunge (stream);
  272.     mail_close (stream);
  273.     stream = NIL;
  274.     break;
  275.       case '+':
  276.     mail_debug (stream); debug = T;
  277.     break;
  278.       case '-':
  279.     mail_nodebug (stream); debug = NIL;
  280.     break;
  281.       case '?':            /* ? command */
  282.     puts ("Check, Delete, Expunge, Find, GC, Headers, New Mailbox,");
  283.     puts (" Quit, Send, Type, Undelete, Xit,");
  284.     puts (" +, -, or <RETURN> for next message");
  285.     break;
  286.       case '\0':        /* null command (type next message) */
  287.     if (last > 0 && last++ < stream->nmsgs) {
  288.       printf ("%s",mail_fetchheader (stream,last));
  289.       puts (mail_fetchtext (stream,last));
  290.     }
  291.     else puts ("%No next message");
  292.     break;
  293.       default:            /* bogus command */
  294.     printf ("?Unrecognized command: %s\n",cmd);
  295.     break;
  296.     }
  297.   }
  298. }
  299.  
  300. /* MM display header
  301.  * Accepts: IMAP2 stream
  302.  *        message number
  303.  */
  304.  
  305. void header (stream,msgno)
  306.     MAILSTREAM *stream;
  307.     long msgno;
  308. {
  309.   long i;
  310.   char tmp[256];
  311.   char *t;
  312.   MESSAGECACHE *cache = mail_elt (stream,msgno);
  313.   mail_fetchenvelope (stream,msgno);
  314.   tmp[0] = cache->recent ? (cache->seen ? 'R': 'N') : ' ';
  315.   tmp[1] = (cache->recent | cache->seen) ? ' ' : 'U';
  316.   tmp[2] = cache->flagged ? 'F' : ' ';
  317.   tmp[3] = cache->answered ? 'A' : ' ';
  318.   tmp[4] = cache->deleted ? 'D' : ' ';
  319.   sprintf (tmp+5,"%4ld) ",cache->msgno);
  320.   strncpy (tmp+11,cache->internal_date ? cache->internal_date : "dd-mmm",6);
  321.   tmp[17] = ' ';
  322.   tmp[18] = '\0';
  323.   mail_fetchfrom (tmp+18,stream,msgno,(long) 20);
  324.   strcat (tmp," ");
  325.   if (i = cache->user_flags) {
  326.     strcat (tmp,"{");
  327.     while (i) {
  328.       strcat (tmp,stream->user_flags[find_rightmost_bit (&i)]);
  329.       if (i) strcat (tmp," ");
  330.     }
  331.     strcat (tmp,"} ");
  332.   }
  333.   mail_fetchsubject (t = tmp + strlen (tmp),stream,msgno,(long) 25);
  334.   sprintf (t += strlen (t)," (%ld chars)",cache->rfc822_size);
  335.   puts (tmp);
  336. }
  337.  
  338. /* MM status report
  339.  * Accepts: MAIL stream
  340.  */
  341.  
  342. void status (stream)
  343.     MAILSTREAM *stream;
  344. {
  345.   long i;
  346.   char date[50];
  347.   rfc822_date (date);
  348.   puts (date);
  349.   if (stream) {
  350.     if (stream->mailbox) printf ("Mailbox: %s, %ld messages, %ld recent\n",
  351.                  stream->mailbox,stream->nmsgs,stream->recent);
  352.     else puts ("%No mailbox is open on this stream");
  353.     if (stream->user_flags[0]) {
  354.       printf ("Keywords: %s",stream->user_flags[0]);
  355.       for (i = 1; i < NUSERFLAGS && stream->user_flags[i]; ++i)
  356.     printf (", %s",stream->user_flags[i]);
  357.       puts ("");
  358.     }
  359.   }
  360. }
  361.  
  362.  
  363. /* Prompt user for input
  364.  * Accepts: pointer to prompt message
  365.  *          pointer to input buffer
  366.  */
  367.  
  368. void prompt (msg,txt)
  369.     char *msg;
  370.     char *txt;
  371. {
  372.   printf ("%s",msg);
  373.   gets (txt);
  374. }
  375.  
  376. /* Interfaces to C-client */
  377.  
  378.  
  379. void mm_searched (stream,number)
  380.     MAILSTREAM *stream;
  381.     long number;
  382. {
  383. }
  384.  
  385.  
  386. void mm_exists (stream,number)
  387.     MAILSTREAM *stream;
  388.     long number;
  389. {
  390. }
  391.  
  392.  
  393. void mm_expunged (stream,number)
  394.     MAILSTREAM *stream;
  395.     long number;
  396. {
  397. }
  398.  
  399.  
  400. void mm_notify (stream,string,errflg)
  401.     MAILSTREAM *stream;
  402.     char *string;
  403.     long errflg;
  404. {
  405.   mm_log (string,errflg);
  406. }
  407.  
  408.  
  409. void mm_mailbox (string)
  410.     char *string;
  411. {
  412.   putchar (' ');
  413.   puts (string);
  414. }
  415.  
  416.  
  417. void mm_bboard (string)
  418.     char *string;
  419. {
  420.   putchar (' ');
  421.   puts (string);
  422. }
  423.  
  424. void mm_log (string,errflg)
  425.     char *string;
  426.     long errflg;
  427. {
  428.   switch ((short) errflg) {
  429.   case NIL:
  430.     printf ("[%s]\n",string);
  431.     break;
  432.   case PARSE:
  433.   case WARN:
  434.     printf ("%%%s\n",string);
  435.     break;
  436.   case ERROR:
  437.     printf ("?%s\n",string);
  438.     break;
  439.   }
  440. }
  441.  
  442.  
  443. void mm_dlog (string)
  444.     char *string;
  445. {
  446.   puts (string);
  447. }
  448.  
  449.  
  450. void mm_login (host,user,pwd,trial)
  451.     char *host;
  452.     char *user;
  453.     char *pwd;
  454.     long trial;
  455. {
  456.   char tmp[MAILTMPLEN];
  457.   if (curhst) fs_give ((void **) &curhst);
  458.   curhst = (char *) fs_get (1+strlen (host));
  459.   strcpy (curhst,host);
  460.   sprintf (tmp,"{%s} username: ",host);
  461.   prompt (tmp,user);
  462.   if (curusr) fs_give ((void **) &curusr);
  463.   curusr = (char *) fs_get (1+strlen (user));
  464.   strcpy (curusr,user);
  465.   prompt ("password: ",pwd);
  466. }
  467.  
  468.  
  469. void mm_critical (stream)
  470.     MAILSTREAM *stream;
  471. {
  472. }
  473.  
  474.  
  475. void mm_nocritical (stream)
  476.     MAILSTREAM *stream;
  477. {
  478. }
  479.  
  480.  
  481. long mm_diskerror (stream,errcode,serious)
  482.     MAILSTREAM *stream;
  483.     long errcode;
  484.     long serious;
  485. {
  486. #if unix
  487.   kill (getpid (),SIGSTOP);
  488. #else
  489.   abort ();
  490. #endif
  491.   return NIL;
  492. }
  493.  
  494.  
  495. void mm_fatal (string)
  496.     char *string;
  497. {
  498.   printf ("?%s\n",string);
  499. }
  500.  
  501. /* SMTP tester */
  502.  
  503. void smtptest (debug)
  504.     long debug;
  505. {
  506.   SMTPSTREAM *stream = NIL;
  507.   char line[MAILTMPLEN];
  508.   unsigned char *text = (unsigned char *) fs_get (8*MAILTMPLEN);
  509.   ENVELOPE *msg = mail_newenvelope ();
  510.   BODY *body = mail_newbody ();
  511.   sprintf (line,"%s <%s@%s>",personalname,curusr,curhst);
  512.   rfc822_parse_adrlist (&msg->from,line,curhst);
  513.   sprintf (line,"%s@%s",curusr,curhst);
  514.   rfc822_parse_adrlist (&msg->return_path,line,curhst);
  515.   prompt ("To: ",line);
  516.   rfc822_parse_adrlist (&msg->to,line,curhst);
  517.   if (msg->to) {
  518.     prompt ("cc: ",line);
  519.     rfc822_parse_adrlist (&msg->cc,line,curhst);
  520.   }
  521.   else {
  522.     prompt ("Newsgroups: ",line);
  523.     if (*line) msg->newsgroups = cpystr (line);
  524.     else {
  525.       mail_free_body (&body);
  526.       mail_free_envelope (&msg);
  527.       fs_give ((void **) &text);
  528.     }
  529.   }
  530.   prompt ("Subject: ",line);
  531.   msg->subject = cpystr (line);
  532.   puts (" Msg (end with a line with only a '.'):");
  533.   body->type = TYPETEXT;
  534.   *text = '\0';
  535.   while (gets (line)) {
  536.     if (line[0] == '.') {
  537.       if (line[1] == '\0') break;
  538.       else strcat ((char *) text,".");
  539.     }
  540.     strcat ((char *) text,line);
  541.     strcat ((char *) text,"\015\012");
  542.   }
  543.   body->contents.text = text;
  544.   rfc822_date (line);
  545.   msg->date = (char *) fs_get (1+strlen (line));
  546.   strcpy (msg->date,line);
  547.   if (msg->to) {
  548.     puts ("Sending...");
  549.     if (stream = smtp_open (hostlist,debug)) {
  550.       if (smtp_mail (stream,"MAIL",msg,body)) puts ("[Ok]");
  551.       else printf ("[Failed - %s]\n",stream->reply);
  552.     }
  553.   }
  554.   else {
  555.     puts ("Posting...");
  556.     if (stream = nntp_open (newslist,debug)) {
  557.       if (nntp_mail (stream,msg,body)) puts ("[Ok]");
  558.       else printf ("[Failed - %s]\n",stream->reply);
  559.     }
  560.   }
  561.   if (stream) smtp_close (stream);
  562.   else puts ("[Can't open connection to any server]");
  563.   mail_free_envelope (&msg);
  564.   mail_free_body (&body);
  565. }
  566.